#ifndef MESH_GRID_H_
#define MESH_GRID_H_

#include "Renderable.h"
#include "Grid.h"
#include <string>
#include <vector>
class Texture;

/* Usefull wrapper for indexed meshes */
struct IndexedTriangle
{
    IndexedTriangle()
    {
        m_vertIndex[0] = m_vertIndex[1] = m_vertIndex[2] = 0;
        m_uvIndex[0] = m_uvIndex[1] = m_uvIndex[2] = 0;
        m_normalIndex[0] = m_normalIndex[1] = m_vertIndex[2] = 0;
        m_materialIndex = -1;
    }
    int m_vertIndex[3];
    int m_uvIndex[3];
    int m_normalIndex[3];
    int m_materialIndex;
};
/* Usefull wrapper for materials */
struct obj_material
{
    obj_material() : textureLookup(0) {}
    std::string name;
    unsigned int textureLookup;
};

typedef std::vector<IndexedTriangle> vTriangle;
typedef std::vector<obj_material>   vMaterial;
typedef std::vector<Texture*>   vTexture;
typedef std::vector<Vec3> vVec3;
//HAHA HACKED
typedef std::vector<Vec3> vVec2;

class MeshGrid : public Renderable
{
public:
    MeshGrid(Scene& scene) : 
    m_triangleCount(0),
    m_totalVerts(0),
    m_texture(NULL),
    m_grid(scene,m_renderables) 
    {}
    MeshGrid(Scene& scene, const Material& m, bool reflect,
                                         float reflectance) : 
    Renderable(m,reflect,reflectance),
    m_triangleCount(0),
    m_totalVerts(0),
    m_texture(NULL),
    m_grid(scene,m_renderables) 
    {}
    MeshGrid(Scene& scene, const Material& m, bool reflect,
         float reflectance, bool transparent, float opacity) : 
    Renderable(m,reflect,reflectance,transparent,opacity),
    m_triangleCount(0),
    m_totalVerts(0),
    m_texture(NULL),
    m_grid(scene,m_renderables) 
    {}
    ~MeshGrid(){CleanUp();}
/************************************************************************/
/* MAIN USE FUCNTIONS                                                   */
/************************************************************************/
    bool CreateFromOBJ(const char* fileName, const Vec3& scale);
    /* Each mesh can have one texture currently, */
    void SetTexture(Texture* tex){m_texture = tex;}
    void CleanUp();
    virtual bool Hit(const Ray& ray, float& tmin, ContactData& data) const;

#ifdef DEBUGGING
    virtual bool Hit_Debug(const Ray& ray, float& tmin, ContactData& data) const;
#endif
    void SetMaterial(const Material& m){m_material = m;}
    virtual void CalculateBox();
    void GenerateGrid(bool sShading, bool textured);
/************************************************************************/
/* HELPER FUNCTIONS                                                     */
/************************************************************************/
private:
    /* Create Functions */
    void CreateVertex   (const std::string& s);
    void CreateNormal   (const std::string& s);
    void CreateUv       (const std::string& s);
    void CreateTri      (const std::string& s);
    void GetFloat       (const std::string& source, std::string* target);
    void Create         (std::string* store, Vec3* v3, int num);
    void GetInts        (int* i, std::string s);
    float StoF          (const std::string& s);
    int StoI            (const std::string& s);
    bool LoadInMaterials( const std::string& s );

/************************************************************************/
/* GET FUNCTIONS                                                        */
/************************************************************************/
public:
    int VertexCount() const { return m_totalVerts; }    
    int TriangleCount() const { return m_triangleCount; }
    void ReverseNormals();
    void CreateMaterial( const std::string& s, File& file );
    void AssignCurrentMaterial(const std::string& s);
    /************************************************************************/
/* MEMBER DATA                                                          */
/************************************************************************/
private:
    int m_totalVerts;
    int m_triangleCount;
    vTriangle m_triangles;
    vMaterial m_materials;
    vTexture m_textures;
    vRenderables m_renderables;
    vVec2 m_uvs;
    vVec3 m_normals;
    vVec3 m_verts;
    bool m_sShading;
    //this is an externally managed texture, does not need deleting!
    Texture* m_texture;
    //acceleration structure
    Grid m_grid;
    std::string m_currentMaterial;
};
#endif
